package com.example.rbacmanage.controller.app;

import cn.hutool.core.date.DateUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.druid.util.StringUtils;
import com.example.rbacmanage.annotation.CurrentUser;
import com.example.rbacmanage.common.Result;
import com.example.rbacmanage.common.enums.OrderStatusEnum;
import com.example.rbacmanage.entity.app.AppUser;
import com.example.rbacmanage.entity.app.MenuOrder;
import com.example.rbacmanage.entity.app.MinAppConfig;
import com.example.rbacmanage.property.DefinedProperty;
import com.example.rbacmanage.service.app.AppUserService;
import com.example.rbacmanage.service.app.MenuOrderService;
import com.example.rbacmanage.service.app.MinAppConfigService;
import com.example.rbacmanage.util.WxUtil;
import com.example.rbacmanage.vo.PayReq;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse;
import com.wechat.pay.java.service.payments.model.Transaction;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;
@Slf4j
@RestController
@RequestMapping("/app/minappconfig")
public class MinAppConfigAppController {
    @Autowired
    private MinAppConfigService minAppConfigService;
    @Autowired
    private DefinedProperty definedProperty;
    @Autowired
    private AppUserService appUserService;
    @Autowired
    private MenuOrderService menuOrderService;
    /**
     * 获取微信支付信息
     * @return
     */
    @PostMapping("/getWxPayInfo")
    public Result info(@CurrentUser Long userId, @RequestBody PayReq payReq){
        AppUser appUser = appUserService.getById(userId);
        if (appUser != null) {
            payReq.setOpenId(appUser.getOpenId());
        }
        MinAppConfig minAppConfig = minAppConfigService.getOneByShopIdAndType(payReq.getShopId(), "0");
        if (minAppConfig !=null
        && !StringUtils.isEmpty(minAppConfig.getMerchantId())
        && !StringUtils.isEmpty(minAppConfig.getPrivateKeyPath())
        && !StringUtils.isEmpty(minAppConfig.getMerchantSerialNumber())
        && !StringUtils.isEmpty(minAppConfig.getApiV3Key())
        ){
            minAppConfig.setPrivateKeyPath(minAppConfig.getPrivateKeyPath().replace("/profile/",definedProperty.getUploadProfile()));
            minAppConfig.setPublicKeyPath(minAppConfig.getPublicKeyPath().replace("/profile/",definedProperty.getUploadProfile()));
            String out_trade_no = DateUtil.format(new Date(),"yyyyMMddHHmmssSSS");
            PrepayWithRequestPaymentResponse requestPaymentResponse =
                    WxUtil.startJsapiPayment(minAppConfig.getMerchantId(),
                    minAppConfig.getPrivateKeyPath(),minAppConfig.getPublicKeyPath(),minAppConfig.getMerchantSerialNumber()
            ,minAppConfig.getApiV3Key(),minAppConfig.getAppId(),payReq.getAmount(),payReq.getMenuOrderIds().stream()
                                    .map(String::valueOf)
                                    .collect(Collectors.joining("&")),payReq.getOpenId(),minAppConfig.getPublicKeyId(),out_trade_no);
            if (requestPaymentResponse != null) {
                List<Long> menuOrderIds = payReq.getMenuOrderIds();
                Date orderdate = new Date();
                for (Long menuOrderId : menuOrderIds) {
                    MenuOrder menuOrder = new MenuOrder();
                    menuOrder.setTransactionNumber(out_trade_no);
                    menuOrder.setOrderStatus(OrderStatusEnum.PAYMENT_ON_BEHALF.getType());
                    menuOrder.setOrderTime(orderdate);
                    menuOrder.setId(menuOrderId);
                    menuOrderService.update(menuOrder);
                }
                //超过24小时未支付，则关闭订单
                Timer timer = new Timer();
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(orderdate);
                calendar.add(Calendar.HOUR_OF_DAY, 24);
                Date date = calendar.getTime();
                timer.schedule(new CloseOrderTask(out_trade_no,minAppConfig,menuOrderIds),date);
            }
            return Result.success(requestPaymentResponse);
        }
        return Result.success();
    }
    public static class CloseOrderTask extends TimerTask {
        private String out_trade_no;
        private MinAppConfig minAppConfig;
        private List<Long> menuOrderIds;
        public CloseOrderTask(String out_trade_no, MinAppConfig minAppConfig,List<Long> menuOrderIds) {
            this.out_trade_no = out_trade_no;
            this.minAppConfig = minAppConfig;
            this.menuOrderIds = menuOrderIds;
        }
        @Override
        public void run() {
            Transaction transaction = WxUtil.queryOrderByOutTradeNo(minAppConfig.getMerchantId(),
                    minAppConfig.getPrivateKeyPath(),minAppConfig.getPublicKeyPath(),minAppConfig.getMerchantSerialNumber()
                    ,minAppConfig.getApiV3Key(),out_trade_no,minAppConfig.getPublicKeyId());
            log.info("查询是否存在支付的订单{}",transaction.toString());
            if (transaction != null && (transaction.getTradeState().name().equals("NOTPAY") || transaction.getTradeState().name().equals("USERPAYING"))
             || transaction.getTradeState().name().equals("PAYERROR")) {
                WxUtil.closeOrder(minAppConfig.getMerchantId(),
                        minAppConfig.getPrivateKeyPath(),minAppConfig.getPublicKeyPath(),minAppConfig.getMerchantSerialNumber()
                        ,minAppConfig.getApiV3Key(),out_trade_no,minAppConfig.getPublicKeyId());
                transaction = WxUtil.queryOrderByOutTradeNo(minAppConfig.getMerchantId(),
                        minAppConfig.getPrivateKeyPath(),minAppConfig.getPublicKeyPath(),minAppConfig.getMerchantSerialNumber()
                        ,minAppConfig.getApiV3Key(),out_trade_no,minAppConfig.getPublicKeyId());
                if (transaction != null && transaction.getTradeState().name().equals("CLOSED") && menuOrderIds != null
                && !menuOrderIds.isEmpty()) {
                    MenuOrderService menuOrderService = SpringUtil.getBean(MenuOrderService.class);
                    for (Long menuOrderId : menuOrderIds) {
                        MenuOrder menuOrder = new MenuOrder();
                        menuOrder.setOrderStatus(OrderStatusEnum.CLOSED.getType());
                        menuOrder.setCreateTime(new Date());
                        menuOrder.setId(menuOrderId);
                        menuOrderService.update(menuOrder);
                    }
                }
            }
        }
    }
}
